home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / cps1.c < prev    next >
C/C++ Source or Header  |  2000-05-04  |  58KB  |  1,945 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw.c
  4.  
  5.   Functions to emulate the video hardware of the machine.
  6.  
  7.   Todo:
  8.   7 unknown attribute bits on scroll 2/3.
  9.   Speed, speed, speed...
  10.  
  11.   OUTPUT PORTS (preliminary)
  12.   0x00-0x01     OBJ RAM base (/256)
  13.   0x02-0x03     Scroll1 RAM base (/256)
  14.   0x04-0x05     Scroll2 RAM base (/256)
  15.   0x06-0x07     Scroll3 RAM base (/256)
  16.   0x08-0x09     "Other" RAM - Scroll distortion (/256)
  17.   0x0a-0x0b     Palette base (/256)
  18.   0x0c-0x0d     Scroll 1 X
  19.   0x0e-0x0f     Scroll 1 Y
  20.   0x10-0x11     Scroll 2 X
  21.   0x12-0x13     Scroll 2 Y
  22.   0x14-0x15     Scroll 3 X
  23.   0x16-0x17     Scroll 3 Y
  24.   0x18-0x19     Related to X pos (xored with 0x1e0 then 0x20 added when flip)
  25.   0x1a-0x1b     Related to Y pos (xored with 0x100 when screen flip on)
  26.   0x1c-0x1d     Related to X pos (xored with 0x1e0 then 0x20 added when flip)
  27.   0x1e-0x1f     Related to Y pos (xored with 0x100 when screen flip on)
  28.   0x20-0x21     start offset for the rowscroll matrix
  29.   0x22-0x23     unknown but widely used - usually 0x0e. bit 0 enables rowscroll
  30.                 on layer 2. bit 15 is flip screen.
  31.  
  32.  
  33.   Registers move from game to game.. following example strider
  34.   0x66-0x67     Video control register (location varies according to game)
  35.   0x68-0x69     Priority mask
  36.   0x6a-0x6b     Priority mask
  37.   0x6c-0x6d     Priority mask
  38.   0x6e-0x6f     Priority mask
  39.   0x70-0x71     Control register (usually 0x003f)
  40.  
  41.   Fixed registers
  42.   0x80-0x81     Sound command
  43.   0x88-0x89     Sound fade
  44.  
  45.   Known Bug List
  46.   ==============
  47.   All games
  48.   * Large sprites don't exit smoothly on the left side of the screen (e.g. Car
  49.     in Mega Man attract mode, cadillac in Cadillacs and Dinosaurs)
  50.  
  51.   Magic Sword.
  52.   * during attract mode, characters are shown with a black background. There is
  53.     a background, but the layers are disabled. I think this IS the correct
  54.     behaviour.
  55.  
  56.   King of Dragons.
  57.   * Distortion effect missing on character description screen during attract
  58.     mode. The game rapidly toggles on and off the layer enable bit.
  59.  
  60.   mtwins
  61.   * in the cave, some parts of the background don't wave. That's because
  62.     rowscroll is not supported for high priority tiles.
  63.  
  64.   cawing
  65.   * at end of level 2, a big black box covers the large plane. This seems to
  66.     be supposed to be a *mask* to hide the fuel pipes. The pipes are sprites,
  67.     the large plane is scroll2. Therefore, the mask should block sprites but
  68.     not tiles from the other planes.
  69.  
  70.   qad
  71.   * layer enable mask incomplete
  72.  
  73.    dino
  74.   * in level 6, the legs of the big dino which stomps you are almost entirely
  75.     missing.
  76.   * in level 6, palette changes due to lightnings cause a lot of tiling effects
  77.     on scroll2.
  78.  
  79.   Unknown issues
  80.   ==============
  81.  
  82.   There are often some redundant high bits in the scroll layer's attributes.
  83.   I think that these are spare bits that the game uses for control.
  84.   The games seem to use them to mark platforms, kill zones and no-go areas.
  85.  
  86. ***************************************************************************/
  87.  
  88. #include "driver.h"
  89. #include "vidhrdw/generic.h"
  90. #include "drivers/cps1.h"
  91.  
  92. #define VERBOSE 0
  93.  
  94. #ifdef MAME_DEBUG
  95. #define CPS1_DUMP_VIDEO 1
  96. #else
  97. #define CPS1_DUMP_VIDEO 0
  98. #endif
  99.  
  100.  
  101. /********************************************************************
  102.  
  103.             Configuration table:
  104.  
  105. ********************************************************************/
  106.  
  107. /* Game specific data */
  108. struct CPS1config
  109. {
  110.     char *name;             /* game driver name */
  111.  
  112.     /* Some games interrogate a couple of registers on bootup. */
  113.     /* These are CPS1 board B self test checks. They wander from game to */
  114.     /* game. */
  115.     int cpsb_addr;        /* CPS board B test register address */
  116.     int cpsb_value;       /* CPS board B test register expected value */
  117.  
  118.     /* some games use as a protection check the ability to do 16-bit multiplies */
  119.     /* with a 32-bit result, by writing the factors to two ports and reading the */
  120.     /* result from two other ports. */
  121.     /* It looks like this feature was introduced with 3wonders (CPSB ID = 08xx) */
  122.     int mult_factor1;
  123.     int mult_factor2;
  124.     int mult_result_lo;
  125.     int mult_result_hi;
  126.  
  127.     int layer_control;
  128.     int priority0;
  129.     int priority1;
  130.     int priority2;
  131.     int priority3;
  132.     int control_reg;  /* Control register? seems to be always 0x3f */
  133.  
  134.     /* ideally, the layer enable masks should consist of only one bit, */
  135.     /* but in many cases it is unknown which bit is which. */
  136.     int scrl1_enable_mask;
  137.     int scrl2_enable_mask;
  138.     int scrl3_enable_mask;
  139.  
  140.     int bank_scroll1;
  141.     int bank_scroll2;
  142.     int bank_scroll3;
  143.  
  144.     /* Some characters aren't visible */
  145.     const int space_scroll1;
  146.     const int start_scroll2;
  147.     const int end_scroll2;
  148.     const int start_scroll3;
  149.     const int end_scroll3;
  150.  
  151.     int kludge;  /* Ghouls n Ghosts sprite kludge */
  152. };
  153.  
  154. struct CPS1config *cps1_game_config;
  155.  
  156. static struct CPS1config cps1_config_table[]=
  157. {
  158.     /* name       CPSB ID    multiply protection  ctrl    priority masks  unknwn  layer enable   banks spacechr kludge */
  159.     {"forgottn",0x00,0x0000, 0x00,0x00,0x00,0x00, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x04,0x08, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff, 7},
  160.     {"lostwrld",0x00,0x0000, 0x00,0x00,0x00,0x00, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x04,0x08, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff, 7},
  161.     {"ghouls",  0x00,0x0000, 0x00,0x00,0x00,0x00, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x04,0x08, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff, 1},
  162.     {"ghoulsu", 0x00,0x0000, 0x00,0x00,0x00,0x00, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x04,0x08, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff, 1},
  163.     {"ghoulsj", 0x00,0x0000, 0x00,0x00,0x00,0x00, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x04,0x08, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff, 1},
  164.     {"strider", 0x00,0x0000, 0x00,0x00,0x00,0x00, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x0c,0x0c, 1,0,1,     -1,0x0000,0xffff,0x0000,0xffff },
  165.     {"striderj",0x00,0x0000, 0x00,0x00,0x00,0x00, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x0c,0x0c, 1,0,1,     -1,0x0000,0xffff,0x0000,0xffff },
  166.     {"stridrja",0x00,0x0000, 0x00,0x00,0x00,0x00, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x0c,0x0c, 1,0,1,     -1,0x0000,0xffff,0x0000,0xffff },
  167.     {"dwj",     0x00,0x0000, 0x00,0x00,0x00,0x00, 0x6c,0x6a,0x68,0x66,0x64,0x62, 0x02,0x04,0x08, 0,1,1,     -1,0x0000,0xffff,0x0000,0xffff },
  168.     {"willow",  0x00,0x0000, 0x00,0x00,0x00,0x00, 0x70,0x6e,0x6c,0x6a,0x68,0x66, 0x20,0x10,0x08, 0,1,0,     -1,0x0000,0xffff,0x0000,0xffff },
  169.     {"willowj", 0x00,0x0000, 0x00,0x00,0x00,0x00, 0x70,0x6e,0x6c,0x6a,0x68,0x66, 0x20,0x10,0x08, 0,1,0,     -1,0x0000,0xffff,0x0000,0xffff },
  170.     {"unsquad", 0x00,0x0000, 0x00,0x00,0x00,0x00, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x38,0x38,0x38, 0,0,0,     -1,0x0000,0xffff,0x0001,0xffff },
  171.     {"area88",  0x00,0x0000, 0x00,0x00,0x00,0x00, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x38,0x38,0x38, 0,0,0,     -1,0x0000,0xffff,0x0001,0xffff },
  172.     {"ffight",  0x60,0x0004, 0x00,0x00,0x00,0x00, 0x6e,0x66,0x70,0x68,0x72,0x6a, 0x02,0x0c,0x0c, 0,0,0,     -1,0x0001,0xffff,0x0001,0xffff },
  173.     {"ffightu", 0x00,0x0000, 0x00,0x00,0x00,0x00, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x0c,0x0c, 0,0,0,     -1,0x0001,0xffff,0x0001,0xffff },
  174.     {"ffightj", 0x60,0x0004, 0x00,0x00,0x00,0x00, 0x6e,0x66,0x70,0x68,0x72,0x6a, 0x02,0x0c,0x0c, 0,0,0,     -1,0x0001,0xffff,0x0001,0xffff },
  175.     {"1941",    0x60,0x0005, 0x00,0x00,0x00,0x00, 0x68,0x6a,0x6c,0x6e,0x70,0x72, 0x02,0x08,0x20, 0,0,0,     -1,0x0000,0xffff,0x0400,0x07ff },
  176.     {"1941j",   0x60,0x0005, 0x00,0x00,0x00,0x00, 0x68,0x6a,0x6c,0x6e,0x70,0x72, 0x02,0x08,0x20, 0,0,0,     -1,0x0000,0xffff,0x0400,0x07ff },
  177.     {"mercs",   0x60,0x0402, 0x00,0x00,0x00,0x00, 0x6c,0x00,0x00,0x00,0x00,0x62, 0x02,0x04,0x08, 0,0,0,     -1,0x0600,0x5bff,0x0700,0x17ff, 4 },    /* (uses port 74) */
  178.     {"mercsu",  0x60,0x0402, 0x00,0x00,0x00,0x00, 0x6c,0x00,0x00,0x00,0x00,0x62, 0x02,0x04,0x08, 0,0,0,     -1,0x0600,0x5bff,0x0700,0x17ff, 4 },    /* (uses port 74) */
  179.     {"mercsj",  0x60,0x0402, 0x00,0x00,0x00,0x00, 0x6c,0x00,0x00,0x00,0x00,0x62, 0x02,0x04,0x08, 0,0,0,     -1,0x0600,0x5bff,0x0700,0x17ff, 4 },    /* (uses port 74) */
  180.     {"mtwins",  0x5e,0x0404, 0x00,0x00,0x00,0x00, 0x52,0x54,0x56,0x58,0x5a,0x5c, 0x38,0x38,0x38, 0,0,0,     -1,0x0000,0xffff,0x0e00,0xffff },
  181.     {"chikij",  0x5e,0x0404, 0x00,0x00,0x00,0x00, 0x52,0x54,0x56,0x58,0x5a,0x5c, 0x38,0x38,0x38, 0,0,0,     -1,0x0000,0xffff,0x0e00,0xffff },
  182.     {"msword",  0x00,0x0000, 0x00,0x00,0x00,0x00, 0x62,0x64,0x66,0x68,0x6a,0x6c, 0x20,0x06,0x06, 0,0,0,     -1,0x2800,0x37ff,0x0000,0xffff },
  183.     {"mswordu", 0x00,0x0000, 0x00,0x00,0x00,0x00, 0x62,0x64,0x66,0x68,0x6a,0x6c, 0x20,0x06,0x06, 0,0,0,     -1,0x2800,0x37ff,0x0000,0xffff },
  184.     {"mswordj", 0x00,0x0000, 0x00,0x00,0x00,0x00, 0x62,0x64,0x66,0x68,0x6a,0x6c, 0x20,0x06,0x06, 0,0,0,     -1,0x2800,0x37ff,0x0000,0xffff },
  185.     {"cawing",  0x40,0x0406, 0x00,0x00,0x00,0x00, 0x4c,0x4a,0x48,0x46,0x44,0x42, 0x10,0x0a,0x0a, 0,0,0, 0x0002,0x0000,0xffff,0x0000,0xffff, 6},    /* row scroll used at the beginning of mission 8, put 07 at ff8501 to jump there */
  186.     {"cawingj", 0x40,0x0406, 0x00,0x00,0x00,0x00, 0x4c,0x4a,0x48,0x46,0x44,0x42, 0x10,0x0a,0x0a, 0,0,0, 0x0002,0x0000,0xffff,0x0000,0xffff, 6},    /* row scroll used at the beginning of mission 8, put 07 at ff8501 to jump there */
  187.     {"nemo",    0x4e,0x0405, 0x00,0x00,0x00,0x00, 0x42,0x44,0x46,0x48,0x4a,0x4c, 0x04,0x22,0x22, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  188.     {"nemoj",   0x4e,0x0405, 0x00,0x00,0x00,0x00, 0x42,0x44,0x46,0x48,0x4a,0x4c, 0x04,0x22,0x22, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  189.     {"sf2",     0x48,0x0407, 0x00,0x00,0x00,0x00, 0x54,0x52,0x50,0x4e,0x4c,0x4a, 0x08,0x12,0x12, 2,2,2,     -1,0x0000,0xffff,0x0000,0xffff },
  190.     {"sf2a",    0x48,0x0407, 0x00,0x00,0x00,0x00, 0x54,0x52,0x50,0x4e,0x4c,0x4a, 0x08,0x12,0x12, 2,2,2,     -1,0x0000,0xffff,0x0000,0xffff },
  191.     {"sf2b",    0x48,0x0407, 0x00,0x00,0x00,0x00, 0x54,0x52,0x50,0x4e,0x4c,0x4a, 0x08,0x12,0x12, 2,2,2,     -1,0x0000,0xffff,0x0000,0xffff },
  192.     {"sf2e",    0xd0,0x0408, 0x00,0x00,0x00,0x00, 0xdc,0xda,0xd8,0xd6,0xd4,0xd2, 0x10,0x0a,0x0a, 2,2,2,     -1,0x0000,0xffff,0x0000,0xffff },
  193.     {"sf2j",    0x6e,0x0403, 0x00,0x00,0x00,0x00, 0x62,0x64,0x66,0x68,0x6a,0x6c, 0x20,0x06,0x06, 2,2,2,     -1,0x0000,0xffff,0x0000,0xffff },
  194.     {"sf2jb",   0x48,0x0407, 0x00,0x00,0x00,0x00, 0x54,0x52,0x50,0x4e,0x4c,0x4a, 0x08,0x12,0x12, 2,2,2,     -1,0x0000,0xffff,0x0000,0xffff },
  195.     {"3wonders",0x72,0x0800, 0x4e,0x4c,0x4a,0x48, 0x68,0x66,0x64,0x62,0x60,0x70, 0x20,0x04,0x08, 0,1,1,     -1,0x0000,0xffff,0x0000,0xffff, 2},
  196.     {"wonder3", 0x72,0x0800, 0x4e,0x4c,0x4a,0x48, 0x68,0x66,0x64,0x62,0x60,0x70, 0x20,0x04,0x08, 0,1,1,     -1,0x0000,0xffff,0x0000,0xffff, 2},
  197.     {"kod",     0x00,0x0000, 0x5e,0x5c,0x5a,0x58, 0x60,0x6e,0x6c,0x6a,0x68,0x70, 0x30,0x08,0x30, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  198.     {"kodj",    0x00,0x0000, 0x5e,0x5c,0x5a,0x58, 0x60,0x6e,0x6c,0x6a,0x68,0x70, 0x30,0x08,0x30, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  199.     {"kodb",    0x00,0x0000, 0x00,0x00,0x00,0x00, 0x60,0x6e,0x6c,0x6a,0x68,0x70, 0x30,0x08,0x30, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  200.     {"captcomm",0x00,0x0000, 0x46,0x44,0x42,0x40, 0x60,0x6e,0x6c,0x6a,0x68,0x70, 0x20,0x12,0x12, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },    /* multiply is used only to center the startup text */
  201.     {"captcomu",0x00,0x0000, 0x46,0x44,0x42,0x40, 0x60,0x6e,0x6c,0x6a,0x68,0x70, 0x20,0x12,0x12, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },    /* multiply is used only to center the startup text */
  202.     {"captcomj",0x00,0x0000, 0x46,0x44,0x42,0x40, 0x60,0x6e,0x6c,0x6a,0x68,0x70, 0x20,0x12,0x12, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },    /* multiply is used only to center the startup text */
  203.     {"knights", 0x00,0x0000, 0x46,0x44,0x42,0x40, 0x68,0x66,0x64,0x62,0x60,0x70, 0x20,0x10,0x02, 0,0,0, 0xf020,0x0000,0xffff,0x0000,0xffff },
  204.     {"knightsj",0x00,0x0000, 0x46,0x44,0x42,0x40, 0x68,0x66,0x64,0x62,0x60,0x70, 0x20,0x10,0x02, 0,0,0, 0xf020,0x0000,0xffff,0x0000,0xffff },
  205.     {"sf2ce",   0x00,0x0000, 0x40,0x42,0x44,0x46, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x0c,0x0c, 2,2,2,     -1,0x0000,0xffff,0x0000,0xffff },
  206.     {"sf2cea",  0x00,0x0000, 0x40,0x42,0x44,0x46, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x0c,0x0c, 2,2,2,     -1,0x0000,0xffff,0x0000,0xffff },
  207.     {"sf2ceb",  0x00,0x0000, 0x40,0x42,0x44,0x46, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x0c,0x0c, 2,2,2,     -1,0x0000,0xffff,0x0000,0xffff },
  208.     {"sf2cej",  0x00,0x0000, 0x40,0x42,0x44,0x46, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x0c,0x0c, 2,2,2,     -1,0x0000,0xffff,0x0000,0xffff },
  209.     {"sf2rb",   0x00,0x0000, 0x40,0x42,0x44,0x46, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x0c,0x0c, 2,2,2,     -1,0x0000,0xffff,0x0000,0xffff },
  210.     {"sf2red",  0x00,0x0000, 0x40,0x42,0x44,0x46, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x0c,0x0c, 2,2,2,     -1,0x0000,0xffff,0x0000,0xffff },
  211.     {"sf2accp2",0x00,0x0000, 0x40,0x42,0x44,0x46, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x0c,0x0c, 2,2,2,     -1,0x0000,0xffff,0x0000,0xffff },
  212.     {"varth",   0x00,0x0000, 0x00,0x00,0x00,0x00, 0x6e,0x66,0x70,0x68,0x72,0x6a, 0x02,0x0c,0x0c, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },    /* CPSB test has been patched out (60=0008) */
  213.     {"varthu",  0x00,0x0000, 0x00,0x00,0x00,0x00, 0x6e,0x66,0x70,0x68,0x72,0x6a, 0x02,0x0c,0x0c, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },    /* CPSB test has been patched out (60=0008) */
  214.     {"varthj",  0x00,0x0000, 0x4e,0x4c,0x4a,0x48, 0x60,0x6e,0x6c,0x6a,0x68,0x70, 0x20,0x06,0x06, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },    /* CPSB test has been patched out (72=0001) */
  215.     {"cworld2j",0x00,0x0000, 0x00,0x00,0x00,0x00, 0x60,0x6e,0x6c,0x6a,0x68,0x70, 0x20,0x14,0x14, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },  /* The 0x76 priority values are incorrect values */
  216.     {"wof",     0x00,0x0000, 0x00,0x00,0x00,0x00, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x04,0x08, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  217.     {"wofj",    0x00,0x0000, 0x00,0x00,0x00,0x00, 0x62,0x64,0x66,0x68,0x6a,0x6c, 0x10,0x08,0x04, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  218.     {"dino",    0x00,0x0000, 0x00,0x00,0x00,0x00, 0x4a,0x4c,0x4e,0x40,0x42,0x44, 0x16,0x16,0x16, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },    /* layer enable never used */
  219.     {"dinoj",   0x00,0x0000, 0x00,0x00,0x00,0x00, 0x4a,0x4c,0x4e,0x40,0x42,0x44, 0x16,0x16,0x16, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },    /* layer enable never used */
  220.     {"punisher",0x4e,0x0c00, 0x00,0x00,0x00,0x00, 0x52,0x54,0x56,0x48,0x4a,0x4c, 0x04,0x02,0x20, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  221.     {"punishru",0x4e,0x0c00, 0x00,0x00,0x00,0x00, 0x52,0x54,0x56,0x48,0x4a,0x4c, 0x04,0x02,0x20, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  222.     {"punishrj",0x4e,0x0c00, 0x00,0x00,0x00,0x00, 0x52,0x54,0x56,0x48,0x4a,0x4c, 0x04,0x02,0x20, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  223.     {"slammast",0x6e,0x0c01, 0x00,0x00,0x00,0x00, 0x56,0x40,0x42,0x68,0x6a,0x6c, 0x10,0x0c,0x0c, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  224.     {"mbomberj",0x6e,0x0c01, 0x00,0x00,0x00,0x00, 0x56,0x40,0x42,0x68,0x6a,0x6c, 0x10,0x0c,0x0c, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  225.     {"mbombrd", 0x5e,0x0c02, 0x00,0x00,0x00,0x00, 0x6a,0x6c,0x6e,0x70,0x72,0x5c, 0x10,0x0c,0x0c, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  226.     {"mbombrdj",0x5e,0x0c02, 0x00,0x00,0x00,0x00, 0x6a,0x6c,0x6e,0x70,0x72,0x5c, 0x10,0x0c,0x0c, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  227.     {"sf2t",    0x00,0x0000, 0x40,0x42,0x44,0x46, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x0c,0x0c, 2,2,2,     -1,0x0000,0xffff,0x0000,0xffff },
  228.     {"sf2tj",   0x00,0x0000, 0x40,0x42,0x44,0x46, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x0c,0x0c, 2,2,2,     -1,0x0000,0xffff,0x0000,0xffff },
  229.     {"pnickj",  0x00,0x0000, 0x00,0x00,0x00,0x00, 0x66,0x00,0x00,0x00,0x00,0x70, 0x0e,0x0e,0x0e, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  230.     {"qad",     0x00,0x0000, 0x00,0x00,0x00,0x00, 0x6c,0x00,0x00,0x00,0x00,0x52, 0x14,0x02,0x14, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  231.     {"qadj",    0x00,0x0000, 0x40,0x42,0x44,0x46, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x0e,0x0e,0x0e, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  232.     {"qtono2",  0x00,0x0000, 0x40,0x42,0x44,0x46, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x06,0x06,0x08, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  233.     {"pang3",   0x00,0x0000, 0x00,0x00,0x00,0x00, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x0c,0x0c, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff, 5},    /* EEPROM port is among the CPS registers */
  234.     {"megaman", 0x00,0x0000, 0x00,0x00,0x00,0x00, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x04,0x08, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  235.     {"rockmanj",0x00,0x0000, 0x00,0x00,0x00,0x00, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x04,0x08, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  236.     {"sfzch",   0x00,0x0000, 0x00,0x00,0x00,0x00, 0x66,0x68,0x6a,0x6c,0x6e,0x70, 0x02,0x04,0x08, 0,0,0,     -1,0x0000,0xffff,0x0000,0xffff },
  237.     {0}        /* End of table */
  238. };
  239.  
  240. static void cps1_init_machine(void)
  241. {
  242.     const char *gamename = Machine->gamedrv->name;
  243.     unsigned char *RAM = memory_region(REGION_CPU1);
  244.  
  245.  
  246.     struct CPS1config *pCFG=&cps1_config_table[0];
  247.     while(pCFG->name)
  248.     {
  249.         if (strcmp(pCFG->name, gamename) == 0)
  250.         {
  251.             break;
  252.         }
  253.         pCFG++;
  254.     }
  255.     cps1_game_config=pCFG;
  256.  
  257.     if (strcmp(gamename, "sf2rb" )==0)
  258.     {
  259.         /* Patch out protection check */
  260.         WRITE_WORD(&RAM[0xe5464],0x6012);
  261.     }
  262. #if 0
  263.     else if (strcmp(gamename, "ghouls" )==0)
  264.     {
  265.         /* Patch out self-test... it takes forever */
  266.         WRITE_WORD(&RAM[0x61964+0], 0x4ef9);
  267.         WRITE_WORD(&RAM[0x61964+2], 0x0000);
  268.         WRITE_WORD(&RAM[0x61964+4], 0x0400);
  269.     }
  270. #endif
  271.   /*
  272.     else if (strcmp(gamename, "slammast" )==0 || strcmp(gamename, "mbomberj" )==0)
  273.     {
  274.         WRITE_WORD(&RAM[0x0fbe], 0x4e75);
  275.     }
  276.     else if (strcmp(gamename, "mbombrd" )==0 || strcmp(gamename, "mbombrdj" )==0)
  277.     {
  278.         WRITE_WORD(&RAM[0x0f1a], 0x4e75);
  279.     }
  280.     */
  281. }
  282.  
  283.  
  284.  
  285. INLINE int cps1_port(int offset)
  286. {
  287.     return READ_WORD(&cps1_output[offset]);
  288. }
  289.  
  290. INLINE unsigned char * cps1_base(int offset,int boundary)
  291. {
  292.     int base=cps1_port(offset)*256;
  293.     /*
  294.     The scroll RAM must start on a 0x4000 boundary.
  295.     Some games do not do this.
  296.     For example:
  297.        Captain commando     - continue screen will not display
  298.        Muscle bomber games  - will animate garbage during gameplay
  299.     Mask out the irrelevant bits.
  300.     */
  301.     base &= ~(boundary-1);
  302.      return &cps1_gfxram[base&0x3ffff];
  303. }
  304.  
  305.  
  306.  
  307. READ_HANDLER( cps1_output_r )
  308. {
  309. #if VERBOSE
  310. if (offset >= 0x18) logerror("PC %06x: read output port %02x\n",cpu_get_pc(),offset);
  311. #endif
  312.  
  313.     /* Some games interrogate a couple of registers on bootup. */
  314.     /* These are CPS1 board B self test checks. They wander from game to */
  315.     /* game. */
  316.     if (offset && offset == cps1_game_config->cpsb_addr)
  317.         return cps1_game_config->cpsb_value;
  318.  
  319.     /* some games use as a protection check the ability to do 16-bit multiplies */
  320.     /* with a 32-bit result, by writing the factors to two ports and reading the */
  321.     /* result from two other ports. */
  322.     if (offset && offset == cps1_game_config->mult_result_lo)
  323.         return (READ_WORD(&cps1_output[cps1_game_config->mult_factor1]) *
  324.                 READ_WORD(&cps1_output[cps1_game_config->mult_factor2])) & 0xffff;
  325.     if (offset && offset == cps1_game_config->mult_result_hi)
  326.         return (READ_WORD(&cps1_output[cps1_game_config->mult_factor1]) *
  327.                 READ_WORD(&cps1_output[cps1_game_config->mult_factor2])) >> 16;
  328.  
  329.     /* Pang 3 EEPROM interface */
  330.     if (cps1_game_config->kludge == 5 && offset == 0x7a)
  331.         return cps1_eeprom_port_r(0);
  332.  
  333.     return READ_WORD(&cps1_output[offset]);
  334. }
  335.  
  336. WRITE_HANDLER( cps1_output_w )
  337. {
  338. #if VERBOSE
  339. if (offset >= 0x18 && //offset != 0x22 &&
  340.         offset != cps1_game_config->layer_control &&
  341.         offset != cps1_game_config->priority0 &&
  342.         offset != cps1_game_config->priority1 &&
  343.         offset != cps1_game_config->priority2 &&
  344.         offset != cps1_game_config->priority3 &&
  345.         offset != cps1_game_config->control_reg)
  346.     logerror("PC %06x: write %02x to output port %02x\n",cpu_get_pc(),data,offset);
  347.  
  348. #ifdef MAME_DEBUG
  349. if (offset == 0x22 && (data & ~0x8001) != 0x0e)
  350. {
  351.     char baf[40];
  352.     sprintf(baf,"port 22 = %02x",data);
  353.     usrintf_showmessage(baf);
  354. }
  355. if (cps1_game_config->priority0 && offset == cps1_game_config->priority0 && data != 0x00)
  356. {
  357.     char baf[40];
  358.     sprintf(baf,"priority0 %04x",data);
  359.     usrintf_showmessage(baf);
  360. }
  361. if (cps1_game_config->control_reg && offset == cps1_game_config->control_reg && data != 0x3f)
  362. {
  363.     char baf[40];
  364.     sprintf(baf,"control_reg %02x",data);
  365.     usrintf_showmessage(baf);
  366. }
  367. #endif
  368. #endif
  369.  
  370.     /* Pang 3 EEPROM interface */
  371.     if (cps1_game_config->kludge == 5 && offset == 0x7a)
  372.     {
  373.         cps1_eeprom_port_w(0,data);
  374.         return;
  375.     }
  376.  
  377.     COMBINE_WORD_MEM(&cps1_output[offset],data);
  378. }
  379.  
  380.  
  381.  
  382. /* Public variables */
  383. unsigned char *cps1_gfxram;
  384. unsigned char *cps1_output;
  385.  
  386.  
  387. size_t cps1_gfxram_size;
  388. size_t cps1_output_size;
  389.  
  390. /* Private */
  391.  
  392. /* Offset of each palette entry */
  393. const int cps1_obj_palette    =0;
  394. const int cps1_scroll1_palette=32;
  395. const int cps1_scroll2_palette=32+32;
  396. const int cps1_scroll3_palette=32+32+32;
  397. #define cps1_palette_entries (32*4)  /* Number colour schemes in palette */
  398.  
  399. const int cps1_scroll1_size=0x4000;
  400. const int cps1_scroll2_size=0x4000;
  401. const int cps1_scroll3_size=0x4000;
  402. const int cps1_obj_size    =0x0800;
  403. const int cps1_other_size  =0x0800;
  404. const int cps1_palette_size=cps1_palette_entries*32; /* Size of palette RAM */
  405. static int cps1_flip_screen;    /* Flip screen on / off */
  406.  
  407. static unsigned char *cps1_scroll1;
  408. static unsigned char *cps1_scroll2;
  409. static unsigned char *cps1_scroll3;
  410. static unsigned char *cps1_obj;
  411. static unsigned char *cps1_buffered_obj;
  412. static unsigned char *cps1_palette;
  413. static unsigned char *cps1_other;
  414. static unsigned char *cps1_old_palette;
  415.  
  416. /* Working variables */
  417. static int cps1_last_sprite_offset;     /* Offset of the last sprite */
  418. static int cps1_layer_enabled[4];       /* Layer enabled [Y/N] */
  419.  
  420. int scroll1x, scroll1y, scroll2x, scroll2y, scroll3x, scroll3y;
  421. static unsigned char *cps1_scroll2_old;
  422. static struct osd_bitmap *cps1_scroll2_bitmap;
  423.  
  424.  
  425. /* Output ports */
  426. #define CPS1_OBJ_BASE            0x00    /* Base address of objects */
  427. #define CPS1_SCROLL1_BASE       0x02    /* Base address of scroll 1 */
  428. #define CPS1_SCROLL2_BASE       0x04    /* Base address of scroll 2 */
  429. #define CPS1_SCROLL3_BASE       0x06    /* Base address of scroll 3 */
  430. #define CPS1_OTHER_BASE            0x08    /* Base address of other video */
  431. #define CPS1_PALETTE_BASE       0x0a    /* Base address of palette */
  432. #define CPS1_SCROLL1_SCROLLX    0x0c    /* Scroll 1 X */
  433. #define CPS1_SCROLL1_SCROLLY    0x0e    /* Scroll 1 Y */
  434. #define CPS1_SCROLL2_SCROLLX    0x10    /* Scroll 2 X */
  435. #define CPS1_SCROLL2_SCROLLY    0x12    /* Scroll 2 Y */
  436. #define CPS1_SCROLL3_SCROLLX    0x14    /* Scroll 3 X */
  437. #define CPS1_SCROLL3_SCROLLY    0x16    /* Scroll 3 Y */
  438.  
  439. #define CPS1_ROWSCROLL_OFFS     0x20    /* base of row scroll offsets in other RAM */
  440.  
  441. #define CPS1_SCROLL2_WIDTH      0x40
  442. #define CPS1_SCROLL2_HEIGHT     0x40
  443.  
  444.  
  445. /*
  446. CPS1 VIDEO RENDERER
  447.  
  448. */
  449. static UINT32 *cps1_gfx;         /* Converted GFX memory */
  450. static int *cps1_char_pen_usage;    /* pen usage array */
  451. static int *cps1_tile16_pen_usage;      /* pen usage array */
  452. static int *cps1_tile32_pen_usage;      /* pen usage array */
  453. static int cps1_max_char;           /* Maximum number of 8x8 chars */
  454. static int cps1_max_tile16;         /* Maximum number of 16x16 tiles */
  455. static int cps1_max_tile32;         /* Maximum number of 32x32 tiles */
  456.  
  457. int cps1_gfx_start(void)
  458. {
  459.     UINT32 dwval;
  460.     int size=memory_region_length(REGION_GFX1);
  461.     unsigned char *data = memory_region(REGION_GFX1);
  462.     int i,j,nchar,penusage,gfxsize;
  463.  
  464.     gfxsize=size/4;
  465.  
  466.     /* Set up maximum values */
  467.     cps1_max_char  =(gfxsize/2)/8;
  468.     cps1_max_tile16=(gfxsize/4)/8;
  469.     cps1_max_tile32=(gfxsize/16)/8;
  470.  
  471.     cps1_gfx=malloc(gfxsize*sizeof(UINT32));
  472.     if (!cps1_gfx)
  473.     {
  474.         return -1;
  475.     }
  476.  
  477.     cps1_char_pen_usage=malloc(cps1_max_char*sizeof(int));
  478.     if (!cps1_char_pen_usage)
  479.     {
  480.         return -1;
  481.     }
  482.     memset(cps1_char_pen_usage, 0, cps1_max_char*sizeof(int));
  483.  
  484.     cps1_tile16_pen_usage=malloc(cps1_max_tile16*sizeof(int));
  485.     if (!cps1_tile16_pen_usage)
  486.         return -1;
  487.     memset(cps1_tile16_pen_usage, 0, cps1_max_tile16*sizeof(int));
  488.  
  489.     cps1_tile32_pen_usage=malloc(cps1_max_tile32*sizeof(int));
  490.     if (!cps1_tile32_pen_usage)
  491.     {
  492.         return -1;
  493.     }
  494.     memset(cps1_tile32_pen_usage, 0, cps1_max_tile32*sizeof(int));
  495.  
  496.     {
  497.         for (i=0; i<gfxsize/2; i++)
  498.         {
  499.             nchar=i/8;  /* 8x8 char number */
  500.            dwval=0;
  501.            for (j=0; j<8; j++)
  502.            {
  503.                 int n,mask;
  504.                 n=0;
  505.                 mask=0x80>>j;
  506.                 if (*(data+size/4)&mask)       n|=1;
  507.                 if (*(data+size/4+1)&mask)     n|=2;
  508.                 if (*(data+size/2+size/4)&mask)    n|=4;
  509.                 if (*(data+size/2+size/4+1)&mask)  n|=8;
  510.                 dwval|=n<<(28-j*4);
  511.                 penusage=1<<n;
  512.                 cps1_char_pen_usage[nchar]|=penusage;
  513.                 cps1_tile16_pen_usage[nchar/2]|=penusage;
  514.                 cps1_tile32_pen_usage[nchar/8]|=penusage;
  515.            }
  516.            cps1_gfx[2*i]=dwval;
  517.            dwval=0;
  518.            for (j=0; j<8; j++)
  519.            {
  520.                 int n,mask;
  521.                 n=0;
  522.                 mask=0x80>>j;
  523.                 if (*(data)&mask)      n|=1;
  524.                 if (*(data+1)&mask)    n|=2;
  525.                 if (*(data+size/2)&mask)   n|=4;
  526.                 if (*(data+size/2+1)&mask) n|=8;
  527.                 dwval|=n<<(28-j*4);
  528.                 penusage=1<<n;
  529.                 cps1_char_pen_usage[nchar]|=penusage;
  530.                 cps1_tile16_pen_usage[nchar/2]|=penusage;
  531.                 cps1_tile32_pen_usage[nchar/8]|=penusage;
  532.            }
  533.            cps1_gfx[2*i+1]=dwval;
  534.            data+=2;
  535.         }
  536.     }
  537.     return 0;
  538. }
  539.  
  540. void cps1_gfx_stop(void)
  541. {
  542.     if (cps1_gfx)
  543.     {
  544.         free(cps1_gfx);
  545.     }
  546.     if (cps1_char_pen_usage)
  547.     {
  548.         free(cps1_char_pen_usage);
  549.     }
  550.     if (cps1_tile16_pen_usage)
  551.     {
  552.         free(cps1_tile16_pen_usage);
  553.     }
  554.     if (cps1_tile32_pen_usage)
  555.     {
  556.         free(cps1_tile32_pen_usage);
  557.     }
  558. }
  559.  
  560.  
  561. void cps1_draw_gfx(
  562.     struct osd_bitmap *dest,const struct GfxElement *gfx,
  563.     unsigned int code,
  564.     int color,
  565.     int flipx,int flipy,
  566.     int sx,int sy,
  567.     int tpens,
  568.     int *pusage,
  569.     const int size,
  570.     const int max,
  571.     const int delta,
  572.     const int srcdelta)
  573. {
  574.     #define DATATYPE unsigned char
  575.     #define IF_NOT_TRANSPARENT(n) if (tpens & (0x01 << n))
  576.     #include "cps1draw.c"
  577.     #undef DATATYPE
  578.     #undef IF_NOT_TRANSPARENT
  579. }
  580.  
  581. void cps1_draw_gfx16(
  582.     struct osd_bitmap *dest,const struct GfxElement *gfx,
  583.     unsigned int code,
  584.     int color,
  585.     int flipx,int flipy,
  586.     int sx,int sy,
  587.     int tpens,
  588.     int *pusage,
  589.     const int size,
  590.     const int max,
  591.     const int delta,
  592.     const int srcdelta)
  593. {
  594.     #define DATATYPE unsigned short
  595.     #define IF_NOT_TRANSPARENT(n) if (tpens & (0x01 << n))
  596.     #include "cps1draw.c"
  597.     #undef DATATYPE
  598.     #undef IF_NOT_TRANSPARENT
  599. }
  600.  
  601. /*
  602.  
  603. This is an optimized version that doesn't take into account transparency
  604.  
  605. Draws complete tiles without checking transparency. Used for scroll 2 low
  606. priority rendering.
  607.  
  608. */
  609. void cps1_draw_gfx_opaque(
  610.     struct osd_bitmap *dest,const struct GfxElement *gfx,
  611.     unsigned int code,
  612.     int color,
  613.     int flipx,int flipy,
  614.     int sx,int sy,
  615.     int tpens,
  616.     int *pusage,
  617.     const int size,
  618.     const int max,
  619.     const int delta,
  620.     const int srcdelta)
  621. {
  622.     #define DATATYPE unsigned char
  623.     #define IF_NOT_TRANSPARENT(n)
  624.     #include "cps1draw.c"
  625.     #undef DATATYPE
  626.     #undef IF_NOT_TRANSPARENT
  627. }
  628.  
  629. void cps1_draw_gfx_opaque16(
  630.     struct osd_bitmap *dest,const struct GfxElement *gfx,
  631.     unsigned int code,
  632.     int color,
  633.     int flipx,int flipy,
  634.     int sx,int sy,
  635.     int tpens,
  636.     int *pusage,
  637.     const int size,
  638.     const int max,
  639.     const int delta,
  640.     const int srcdelta)
  641. {
  642.     #define DATATYPE unsigned short
  643.     #define IF_NOT_TRANSPARENT(n)
  644.     #include "cps1draw.c"
  645.     #undef DATATYPE
  646.     #undef IF_NOT_TRANSPARENT
  647. }
  648.  
  649.  
  650.  
  651. INLINE void cps1_draw_scroll1(
  652.     struct osd_bitmap *dest,
  653.     unsigned int code, int color,
  654.     int flipx, int flipy,int sx, int sy, int tpens)
  655. {
  656.     if (Machine->scrbitmap->depth==16)
  657.     {
  658.         cps1_draw_gfx16(dest,
  659.             Machine->gfx[0],
  660.             code,color,flipx,flipy,sx,sy,
  661.             tpens,cps1_char_pen_usage,8, cps1_max_char, 16, 1);
  662.     }
  663.     else
  664.     {
  665.         cps1_draw_gfx(dest,
  666.             Machine->gfx[0],
  667.             code,color,flipx,flipy,sx,sy,
  668.             tpens,cps1_char_pen_usage,8, cps1_max_char, 16, 1);
  669.     }
  670. }
  671.  
  672.  
  673. INLINE void cps1_draw_tile16(struct osd_bitmap *dest,
  674.     const struct GfxElement *gfx,
  675.     unsigned int code, int color,
  676.     int flipx, int flipy,int sx, int sy, int tpens)
  677. {
  678.     if (Machine->scrbitmap->depth==16)
  679.     {
  680.         cps1_draw_gfx16(dest,
  681.             gfx,
  682.             code,color,flipx,flipy,sx,sy,
  683.             tpens,cps1_tile16_pen_usage,16, cps1_max_tile16, 16*2,0);
  684.     }
  685.     else
  686.     {
  687.         cps1_draw_gfx(dest,
  688.             gfx,
  689.             code,color,flipx,flipy,sx,sy,
  690.             tpens,cps1_tile16_pen_usage,16, cps1_max_tile16, 16*2,0);
  691.     }
  692. }
  693.  
  694. INLINE void cps1_draw_tile32(struct osd_bitmap *dest,
  695.     const struct GfxElement *gfx,
  696.     unsigned int code, int color,
  697.     int flipx, int flipy,int sx, int sy, int tpens)
  698. {
  699.     if (Machine->scrbitmap->depth==16)
  700.     {
  701.         cps1_draw_gfx16(dest,
  702.             gfx,
  703.             code,color,flipx,flipy,sx,sy,
  704.             tpens,cps1_tile32_pen_usage,32, cps1_max_tile32, 16*2*4,0);
  705.     }
  706.     else
  707.     {
  708.         cps1_draw_gfx(dest,
  709.             gfx,
  710.             code,color,flipx,flipy,sx,sy,
  711.             tpens,cps1_tile32_pen_usage,32, cps1_max_tile32, 16*2*4,0);
  712.     }
  713. }
  714.  
  715.  
  716. INLINE void cps1_draw_blank16(struct osd_bitmap *dest, int sx, int sy )
  717. {
  718.     int i,j;
  719.  
  720.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  721.     {
  722.         int temp;
  723.         temp=sx;
  724.         sx=sy;
  725.         sy=dest->height-temp-16;
  726.     }
  727.  
  728.     if (cps1_flip_screen)
  729.     {
  730.         /* Handle flipped screen */
  731.         sx=dest->width-sx-16;
  732.         sy=dest->height-sy-16;
  733.     }
  734.  
  735.     if (Machine->scrbitmap->depth==16)
  736.     {
  737.         for (i=15; i>=0; i--)
  738.         {
  739.             register unsigned short *bm=(unsigned short *)dest->line[sy+i]+sx;
  740.             for (j=15; j>=0; j--)
  741.             {
  742.                 *bm=palette_transparent_pen;
  743.                 bm++;
  744.             }
  745.         }
  746.     }
  747.     else
  748.     {
  749.         for (i=15; i>=0; i--)
  750.         {
  751.             register unsigned char *bm=dest->line[sy+i]+sx;
  752.             for (j=15; j>=0; j--)
  753.             {
  754.                 *bm=palette_transparent_pen;
  755.                 bm++;
  756.             }
  757.         }
  758.     }
  759. }
  760.  
  761.  
  762.  
  763. INLINE void cps1_draw_tile16_bmp(struct osd_bitmap *dest,
  764.     const struct GfxElement *gfx,
  765.     unsigned int code, int color,
  766.     int flipx, int flipy,int sx, int sy)
  767. {
  768.     if (Machine->scrbitmap->depth==16)
  769.     {
  770.         cps1_draw_gfx_opaque16(dest,
  771.             gfx,
  772.             code,color,flipx,flipy,sx,sy,
  773.             -1,cps1_tile16_pen_usage,16, cps1_max_tile16, 16*2,0);
  774.     }
  775.     else
  776.     {
  777.         cps1_draw_gfx_opaque(dest,
  778.             gfx,
  779.             code,color,flipx,flipy,sx,sy,
  780.             -1,cps1_tile16_pen_usage,16, cps1_max_tile16, 16*2,0);
  781.     }
  782. }
  783.  
  784.  
  785.  
  786.  
  787. static int cps1_transparency_scroll[4];
  788.  
  789.  
  790.  
  791. #if CPS1_DUMP_VIDEO
  792. void cps1_dump_video(void)
  793. {
  794.     FILE *fp;
  795.     fp=fopen("SCROLL1.DMP", "w+b");
  796.     if (fp)
  797.     {
  798.         fwrite(cps1_scroll1, cps1_scroll1_size, 1, fp);
  799.         fclose(fp);
  800.     }
  801.     fp=fopen("SCROLL2.DMP", "w+b");
  802.     if (fp)
  803.     {
  804.         fwrite(cps1_scroll2, cps1_scroll2_size, 1, fp);
  805.         fclose(fp);
  806.     }
  807.     fp=fopen("SCROLL3.DMP", "w+b");
  808.     if (fp)
  809.     {
  810.         fwrite(cps1_scroll3, cps1_scroll3_size, 1, fp);
  811.         fclose(fp);
  812.     }
  813.     fp=fopen("OBJ.DMP", "w+b");
  814.     if (fp)
  815.     {
  816.         fwrite(cps1_obj, cps1_obj_size, 1, fp);
  817.         fclose(fp);
  818.     }
  819.  
  820.     fp=fopen("OTHER.DMP", "w+b");
  821.     if (fp)
  822.     {
  823.         fwrite(cps1_other, cps1_other_size, 1, fp);
  824.         fclose(fp);
  825.     }
  826.  
  827.     fp=fopen("PALETTE.DMP", "w+b");
  828.     if (fp)
  829.     {
  830.         fwrite(cps1_palette, cps1_palette_size, 1, fp);
  831.         fclose(fp);
  832.     }
  833.  
  834.     fp=fopen("OUTPUT.DMP", "w+b");
  835.     if (fp)
  836.     {
  837.         fwrite(cps1_output, cps1_output_size, 1, fp);
  838.         fclose(fp);
  839.     }
  840.     fp=fopen("VIDEO.DMP", "w+b");
  841.     if (fp)
  842.     {
  843.         fwrite(cps1_gfxram, cps1_gfxram_size, 1, fp);
  844.         fclose(fp);
  845.     }
  846.  
  847. }
  848. #endif
  849.  
  850.  
  851. INLINE void cps1_get_video_base(void )
  852. {
  853.     int layercontrol;
  854.  
  855.     /* Re-calculate the VIDEO RAM base */
  856.     cps1_scroll1=cps1_base(CPS1_SCROLL1_BASE,cps1_scroll1_size);
  857.     cps1_scroll2=cps1_base(CPS1_SCROLL2_BASE,cps1_scroll2_size);
  858.     cps1_scroll3=cps1_base(CPS1_SCROLL3_BASE,cps1_scroll3_size);
  859.     cps1_obj=cps1_base(CPS1_OBJ_BASE,cps1_obj_size);
  860.     cps1_palette=cps1_base(CPS1_PALETTE_BASE,cps1_palette_size);
  861.     cps1_other=cps1_base(CPS1_OTHER_BASE,cps1_other_size);
  862.  
  863.     /* Get scroll values */
  864.     scroll1x=cps1_port(CPS1_SCROLL1_SCROLLX);
  865.     scroll1y=cps1_port(CPS1_SCROLL1_SCROLLY);
  866.     scroll2x=cps1_port(CPS1_SCROLL2_SCROLLX);
  867.     scroll2y=cps1_port(CPS1_SCROLL2_SCROLLY);
  868.     scroll3x=cps1_port(CPS1_SCROLL3_SCROLLX);
  869.     scroll3y=cps1_port(CPS1_SCROLL3_SCROLLY);
  870.  
  871.     /* Get transparency registers */
  872.     if (cps1_game_config->priority1)
  873.     {
  874.         cps1_transparency_scroll[0]=cps1_port(cps1_game_config->priority0);
  875.         cps1_transparency_scroll[1]=cps1_port(cps1_game_config->priority1);
  876.         cps1_transparency_scroll[2]=cps1_port(cps1_game_config->priority2);
  877.         cps1_transparency_scroll[3]=cps1_port(cps1_game_config->priority3);
  878.     }
  879.  
  880.     /* Get layer enable bits */
  881.     layercontrol=cps1_port(cps1_game_config->layer_control);
  882.     cps1_layer_enabled[0]=1;
  883.     cps1_layer_enabled[1]=layercontrol & cps1_game_config->scrl1_enable_mask;
  884.     cps1_layer_enabled[2]=layercontrol & cps1_game_config->scrl2_enable_mask;
  885.     cps1_layer_enabled[3]=layercontrol & cps1_game_config->scrl3_enable_mask;
  886.  
  887.  
  888. #ifdef MAME_DEBUG
  889. {
  890.     char baf[40];
  891.     int enablemask;
  892.  
  893. if (keyboard_pressed(KEYCODE_Z))
  894. {
  895.     if (keyboard_pressed(KEYCODE_Q)) cps1_layer_enabled[3]=0;
  896.     if (keyboard_pressed(KEYCODE_W)) cps1_layer_enabled[2]=0;
  897.     if (keyboard_pressed(KEYCODE_E)) cps1_layer_enabled[1]=0;
  898.     if (keyboard_pressed(KEYCODE_R)) cps1_layer_enabled[0]=0;
  899.     if (keyboard_pressed(KEYCODE_T))
  900.     {
  901.         sprintf(baf,"%d %d %d %d layer %02x",
  902.             (layercontrol>>0x06)&03,
  903.             (layercontrol>>0x08)&03,
  904.             (layercontrol>>0x0a)&03,
  905.             (layercontrol>>0x0c)&03,
  906.             layercontrol&0xc03f
  907.             );
  908.         usrintf_showmessage(baf);
  909.     }
  910.  
  911. }
  912.  
  913.     enablemask = 0;
  914.     if (cps1_game_config->scrl1_enable_mask == cps1_game_config->scrl2_enable_mask)
  915.         enablemask = cps1_game_config->scrl1_enable_mask;
  916.     if (cps1_game_config->scrl1_enable_mask == cps1_game_config->scrl3_enable_mask)
  917.         enablemask = cps1_game_config->scrl1_enable_mask;
  918.     if (cps1_game_config->scrl2_enable_mask == cps1_game_config->scrl3_enable_mask)
  919.         enablemask = cps1_game_config->scrl2_enable_mask;
  920.     if (enablemask)
  921.     {
  922.         if (((layercontrol & enablemask) && (layercontrol & enablemask) != enablemask))
  923.         {
  924.             sprintf(baf,"layer %02x",layercontrol&0xc03f);
  925.             usrintf_showmessage(baf);
  926.         }
  927.     }
  928.  
  929.     enablemask = cps1_game_config->scrl1_enable_mask | cps1_game_config->scrl2_enable_mask | cps1_game_config->scrl3_enable_mask;
  930. #if 0
  931.     if (((layercontrol & ~enablemask) & 0xc03e) != 0)
  932.     {
  933.         sprintf(baf,"layer %02x",layercontrol&0xc03f);
  934.         usrintf_showmessage(baf);
  935.    }
  936.    #endif
  937. }
  938. #endif
  939. }
  940.  
  941.  
  942. /***************************************************************************
  943.  
  944.   Start the video hardware emulation.
  945.  
  946. ***************************************************************************/
  947.  
  948. int cps1_vh_start(void)
  949. {
  950.     int i;
  951.  
  952.     cps1_init_machine();
  953.  
  954.     if (cps1_gfx_start())
  955.     {
  956.         return -1;
  957.     }
  958.  
  959.     cps1_scroll2_bitmap=osd_new_bitmap(CPS1_SCROLL2_WIDTH*16,
  960.         CPS1_SCROLL2_HEIGHT*16, Machine->scrbitmap->depth );
  961.     if (!cps1_scroll2_bitmap)
  962.     {
  963.         return -1;
  964.     }
  965.     cps1_scroll2_old=malloc(cps1_scroll2_size);
  966.     if (!cps1_scroll2_old)
  967.     {
  968.         return -1;
  969.     }
  970.     memset(cps1_scroll2_old, 0xff, cps1_scroll2_size);
  971.  
  972.  
  973.     cps1_old_palette=(unsigned char *)malloc(cps1_palette_size);
  974.     if (!cps1_old_palette)
  975.     {
  976.         return -1;
  977.     }
  978.     memset(cps1_old_palette, 0x00, cps1_palette_size);
  979.     for (i = 0;i < cps1_palette_entries*16;i++)
  980.     {
  981.        palette_change_color(i,0,0,0);
  982.     }
  983.  
  984.     cps1_buffered_obj = malloc (cps1_obj_size);
  985.     if (!cps1_buffered_obj)
  986.     {
  987.         return -1;
  988.     }
  989.     memset(cps1_buffered_obj, 0x00, cps1_obj_size);
  990.  
  991.     memset(cps1_gfxram, 0, cps1_gfxram_size);   /* Clear GFX RAM */
  992.     memset(cps1_output, 0, cps1_output_size);   /* Clear output ports */
  993.  
  994.     /* Put in some defaults */
  995.     WRITE_WORD(&cps1_output[0x00], 0x9200);
  996.     WRITE_WORD(&cps1_output[0x02], 0x9000);
  997.     WRITE_WORD(&cps1_output[0x04], 0x9040);
  998.     WRITE_WORD(&cps1_output[0x06], 0x9080);
  999.     WRITE_WORD(&cps1_output[0x08], 0x9100);
  1000.     WRITE_WORD(&cps1_output[0x0a], 0x90c0);
  1001.  
  1002.     if (!cps1_game_config)
  1003.     {
  1004.         logerror("cps1_game_config hasn't been set up yet");
  1005.         return -1;
  1006.     }
  1007.  
  1008.  
  1009.     /* Set up old base */
  1010.     cps1_get_video_base();   /* Calculate base pointers */
  1011.     cps1_get_video_base();   /* Calculate old base pointers */
  1012.  
  1013.  
  1014.     for (i=0; i<4; i++)
  1015.     {
  1016.         cps1_transparency_scroll[i]=0x0000;
  1017.     }
  1018.     return 0;
  1019. }
  1020.  
  1021. /***************************************************************************
  1022.  
  1023.   Stop the video hardware emulation.
  1024.  
  1025. ***************************************************************************/
  1026. void cps1_vh_stop(void)
  1027. {
  1028.     if (cps1_old_palette)
  1029.         free(cps1_old_palette);
  1030.     if (cps1_scroll2_bitmap)
  1031.         osd_free_bitmap(cps1_scroll2_bitmap);
  1032.     if (cps1_scroll2_old)
  1033.         free(cps1_scroll2_old);
  1034.     if (cps1_buffered_obj)
  1035.         free(cps1_buffered_obj);
  1036.     cps1_gfx_stop();
  1037. }
  1038.  
  1039. /***************************************************************************
  1040.  
  1041.   Build palette from palette RAM
  1042.  
  1043.   12 bit RGB with a 4 bit brightness value.
  1044.  
  1045. ***************************************************************************/
  1046.  
  1047. void cps1_build_palette(void)
  1048. {
  1049.     int offset;
  1050.  
  1051.     for (offset = 0; offset < cps1_palette_entries*16; offset++)
  1052.     {
  1053.         int palette = READ_WORD (&cps1_palette[offset * 2]);
  1054.  
  1055.         if (palette != READ_WORD (&cps1_old_palette[offset * 2]) )
  1056.         {
  1057.            int red, green, blue, bright;
  1058.  
  1059.            bright= (palette>>12);
  1060.            if (bright) bright += 2;
  1061.  
  1062.            red   = ((palette>>8)&0x0f) * bright;
  1063.            green = ((palette>>4)&0x0f) * bright;
  1064.            blue  = (palette&0x0f) * bright;
  1065.  
  1066.            palette_change_color (offset, red, green, blue);
  1067.            WRITE_WORD(&cps1_old_palette[offset * 2], palette);
  1068.         }
  1069.     }
  1070. }
  1071.  
  1072. /***************************************************************************
  1073.  
  1074.   Scroll 1 (8x8)
  1075.  
  1076.   Attribute word layout:
  1077.   0x0001    colour
  1078.   0x0002    colour
  1079.   0x0004    colour
  1080.   0x0008    colour
  1081.   0x0010    colour
  1082.   0x0020    X Flip
  1083.   0x0040    Y Flip
  1084.   0x0080
  1085.   0x0100
  1086.   0x0200
  1087.   0x0400
  1088.   0x0800
  1089.   0x1000
  1090.   0x2000
  1091.   0x4000
  1092.   0x8000
  1093.  
  1094.  
  1095. ***************************************************************************/
  1096.  
  1097. INLINE void cps1_palette_scroll1(unsigned short *base)
  1098. {
  1099.     int x,y, offs, offsx;
  1100.  
  1101.     int scrlxrough=(scroll1x>>3)+8;
  1102.     int scrlyrough=(scroll1y>>3);
  1103.     int basecode=cps1_game_config->bank_scroll1*0x08000;
  1104.  
  1105.     for (x=0; x<0x36; x++)
  1106.     {
  1107.          offsx=(scrlxrough+x)*0x80;
  1108.          offsx&=0x1fff;
  1109.  
  1110.          for (y=0; y<0x20; y++)
  1111.          {
  1112.             int code, colour, offsy;
  1113.             int n=scrlyrough+y;
  1114.             offsy=( (n&0x1f)*4 | ((n&0x20)*0x100)) & 0x3fff;
  1115.             offs=offsy+offsx;
  1116.             offs &= 0x3fff;
  1117.             code=basecode+READ_WORD(&cps1_scroll1[offs]);
  1118.             colour=READ_WORD(&cps1_scroll1[offs+2]);
  1119.             if (code < cps1_max_char)
  1120.             {
  1121.                 base[colour&0x1f] |=
  1122.                       cps1_char_pen_usage[code]&0x7fff;
  1123.             }
  1124.         }
  1125.     }
  1126. }
  1127.  
  1128. void cps1_render_scroll1(struct osd_bitmap *bitmap,int priority)
  1129. {
  1130.     int x,y, offs, offsx, sx, sy, ytop;
  1131.  
  1132.     int scrlxrough=(scroll1x>>3)+4;
  1133.     int scrlyrough=(scroll1y>>3);
  1134.     int base=cps1_game_config->bank_scroll1*0x08000;
  1135.     const int spacechar=cps1_game_config->space_scroll1;
  1136.  
  1137.  
  1138.     sx=-(scroll1x&0x07);
  1139.     ytop=-(scroll1y&0x07)+32;
  1140.  
  1141.     for (x=0; x<0x35; x++)
  1142.     {
  1143.          sy=ytop;
  1144.          offsx=(scrlxrough+x)*0x80;
  1145.          offsx&=0x1fff;
  1146.  
  1147.          for (y=0; y<0x20; y++)
  1148.          {
  1149.             int code, offsy, colour;
  1150.             int n=scrlyrough+y;
  1151.             offsy=( (n&0x1f)*4 | ((n&0x20)*0x100)) & 0x3fff;
  1152.             offs=offsy+offsx;
  1153.             offs &= 0x3fff;
  1154.  
  1155.             code  =READ_WORD(&cps1_scroll1[offs]);
  1156.             colour=READ_WORD(&cps1_scroll1[offs+2]);
  1157.  
  1158.             if (code != 0x20 && code != spacechar)
  1159.             {
  1160.                 int transp;
  1161.  
  1162.                 /* 0x0020 appears to never be drawn */
  1163.                 if (priority)
  1164.                     transp=cps1_transparency_scroll[(colour & 0x0180)>>7];
  1165.                 else transp = 0x7fff;
  1166.  
  1167.                 cps1_draw_scroll1(bitmap,
  1168.                          code+base,
  1169.                          colour&0x1f,
  1170.                          colour&0x20,
  1171.                          colour&0x40,
  1172.                          sx,sy,transp);
  1173.              }
  1174.              sy+=8;
  1175.          }
  1176.          sx+=8;
  1177.     }
  1178. }
  1179.  
  1180.  
  1181.  
  1182. /***************************************************************************
  1183.  
  1184.                                 Sprites
  1185.                                 =======
  1186.  
  1187.   Sprites are represented by a number of 8 byte values
  1188.  
  1189.   xx xx yy yy nn nn aa aa
  1190.  
  1191.   where xxxx = x position
  1192.         yyyy = y position
  1193.         nnnn = tile number
  1194.         aaaa = attribute word
  1195.                     0x0001    colour
  1196.                     0x0002    colour
  1197.                     0x0004    colour
  1198.                     0x0008    colour
  1199.                     0x0010    colour
  1200.                     0x0020    X Flip
  1201.                     0x0040    Y Flip
  1202.                     0x0080    unknown
  1203.                     0x0100    X block size (in sprites)
  1204.                     0x0200    X block size
  1205.                     0x0400    X block size
  1206.                     0x0800    X block size
  1207.                     0x1000    Y block size (in sprites)
  1208.                     0x2000    Y block size
  1209.                     0x4000    Y block size
  1210.                     0x8000    Y block size
  1211.  
  1212.   The end of the table (may) be marked by an attribute value of 0xff00.
  1213.  
  1214. ***************************************************************************/
  1215.  
  1216. void cps1_find_last_sprite(void)    /* Find the offset of last sprite */
  1217. {
  1218.     int offset=6;
  1219.     /* Locate the end of table marker */
  1220.     while (offset < cps1_obj_size)
  1221.     {
  1222.         int colour=READ_WORD(&cps1_buffered_obj[offset]);
  1223.         if (colour == 0xff00)
  1224.         {
  1225.             /* Marker found. This is the last sprite. */
  1226.             cps1_last_sprite_offset=offset-6-8;
  1227.             return;
  1228.         }
  1229.         offset+=8;
  1230.     }
  1231.     /* Sprites must use full sprite RAM */
  1232.     cps1_last_sprite_offset=cps1_obj_size-8;
  1233. }
  1234.  
  1235. /* Find used colours */
  1236. void cps1_palette_sprites(unsigned short *base)
  1237. {
  1238.     int i;
  1239.  
  1240.     for (i=cps1_last_sprite_offset; i>=0; i-=8)
  1241.     {
  1242.         int x=READ_WORD(&cps1_buffered_obj[i]);
  1243.         int y=READ_WORD(&cps1_buffered_obj[i+2]);
  1244.         if (x && y)
  1245.         {
  1246.             int colour=READ_WORD(&cps1_buffered_obj[i+6]);
  1247.             int col=colour&0x1f;
  1248.             unsigned int code=READ_WORD(&cps1_buffered_obj[i+4]);
  1249.             if (cps1_game_config->kludge == 7)
  1250.             {
  1251.                    code += 0x4000;
  1252.             }
  1253.             if (cps1_game_config->kludge == 1 && code >= 0x01000)
  1254.             {
  1255.                    code += 0x4000;
  1256.             }
  1257.             if (cps1_game_config->kludge == 2 && code >= 0x02a00)
  1258.             {
  1259.                    code += 0x4000;
  1260.             }
  1261.  
  1262.             if ( colour & 0xff00 )
  1263.             {
  1264.                 int nys, nxs;
  1265.                 int nx=(colour & 0x0f00) >> 8;
  1266.                 int ny=(colour & 0xf000) >> 12;
  1267.                 nx++;
  1268.                 ny++;
  1269.  
  1270.                 if (colour & 0x40)   /* Y Flip */                          /* Y flip */
  1271.                 {
  1272.                     if (colour &0x20)
  1273.                     {
  1274.                     for (nys=0; nys<ny; nys++)
  1275.                     {
  1276.                         for (nxs=0; nxs<nx; nxs++)
  1277.                         {
  1278.                             int cod=code+(nx-1)-nxs+0x10*(ny-1-nys);
  1279.                             base[col] |=
  1280.                             cps1_tile16_pen_usage[cod % cps1_max_tile16];
  1281.                         }
  1282.                     }
  1283.                 }
  1284.                 else
  1285.                 {
  1286.                     for (nys=0; nys<ny; nys++)
  1287.                     {
  1288.                         for (nxs=0; nxs<nx; nxs++)
  1289.                         {
  1290.                             int cod=code+nxs+0x10*(ny-1-nys);
  1291.                             base[col] |=
  1292.                             cps1_tile16_pen_usage[cod % cps1_max_tile16];
  1293.                         }
  1294.                     }
  1295.                 }
  1296.             }
  1297.             else
  1298.             {
  1299.                 if (colour &0x20)
  1300.                 {
  1301.                     for (nys=0; nys<ny; nys++)
  1302.                     {
  1303.                         for (nxs=0; nxs<nx; nxs++)
  1304.                         {
  1305.                             int cod=code+(nx-1)-nxs+0x10*nys;
  1306.                             base[col] |=
  1307.                             cps1_tile16_pen_usage[cod % cps1_max_tile16];
  1308.                         }
  1309.                     }
  1310.                 }
  1311.                 else
  1312.                 {
  1313.                     for (nys=0; nys<ny; nys++)
  1314.                     {
  1315.                         for (nxs=0; nxs<nx; nxs++)
  1316.                         {
  1317.                             int cod=code+nxs+0x10*nys;
  1318.                             base[col] |=
  1319.                             cps1_tile16_pen_usage[cod % cps1_max_tile16];
  1320.                         }
  1321.                     }
  1322.                 }
  1323.             }
  1324.             base[col]&=0x7fff;
  1325.             }
  1326.             else
  1327.             {
  1328.                 base[col] |=
  1329.                 cps1_tile16_pen_usage[code % cps1_max_tile16]&0x7fff;
  1330.             }
  1331.         }
  1332.     }
  1333. }
  1334.  
  1335.  
  1336.  
  1337. void cps1_render_sprites(struct osd_bitmap *bitmap)
  1338. {
  1339.     const int mask=0x7fff;
  1340.     int i;
  1341. //mish
  1342.     /* Draw the sprites */
  1343.     for (i=cps1_last_sprite_offset; i>=0; i-=8)
  1344.     {
  1345.         int x=READ_WORD(&cps1_buffered_obj[i]);
  1346.         int y=READ_WORD(&cps1_buffered_obj[i+2]);
  1347.         if (x && y )
  1348.         {
  1349.             unsigned int code=READ_WORD(&cps1_buffered_obj[i+4]);
  1350.             int colour=READ_WORD(&cps1_buffered_obj[i+6]);
  1351.             int col=colour&0x1f;
  1352.  
  1353.             y &= 0x1ff;
  1354.             if (y > 450) y -= 0x200;
  1355.  
  1356.             /* in cawing, skyscrapers parts on level 2 have all the top bits of the */
  1357.             /* x coordinate set. Does this have a special meaning? */
  1358.             x &= 0x1ff;
  1359.             if (x > 450) x -= 0x200;
  1360.  
  1361.             x-=0x20;
  1362.             y+=0x20;
  1363.  
  1364.             if (cps1_game_config->kludge == 7)
  1365.             {
  1366.                    code += 0x4000;
  1367.             }
  1368.             if (cps1_game_config->kludge == 1 && code >= 0x01000)
  1369.             {
  1370.                    code += 0x4000;
  1371.             }
  1372.             if (cps1_game_config->kludge == 2 && code >= 0x02a00)
  1373.             {
  1374.                    code += 0x4000;
  1375.             }
  1376.  
  1377.             if (colour & 0xff00 )
  1378.             {
  1379.                     /* handle blocked sprites */
  1380.                     int nx=(colour & 0x0f00) >> 8;
  1381.                     int ny=(colour & 0xf000) >> 12;
  1382.                     int nxs,nys,sx,sy;
  1383.                     nx++;
  1384.                     ny++;
  1385.  
  1386.                     if (colour & 0x40)
  1387.                     {
  1388.                         /* Y flip */
  1389.                         if (colour &0x20)
  1390.                         {
  1391.                             for (nys=0; nys<ny; nys++)
  1392.                             {
  1393.                                 for (nxs=0; nxs<nx; nxs++)
  1394.                                 {
  1395.                                     sx = x+nxs*16;
  1396.                                     sy = y+nys*16;
  1397.                                     if (sx > 450) sx -= 0x200;
  1398.                                     if (sy > 450) sy -= 0x200;
  1399.  
  1400.                                     cps1_draw_tile16(bitmap,Machine->gfx[1],
  1401.                                         code+(nx-1)-nxs+0x10*(ny-1-nys),
  1402.                                         col&0x1f,
  1403.                                         1,1,
  1404.                                         sx,sy,mask);
  1405.                                 }
  1406.                             }
  1407.                         }
  1408.                         else
  1409.                         {
  1410.                             for (nys=0; nys<ny; nys++)
  1411.                             {
  1412.                                 for (nxs=0; nxs<nx; nxs++)
  1413.                                 {
  1414.                                     sx = x+nxs*16;
  1415.                                     sy = y+nys*16;
  1416.                                     if (sx > 450) sx -= 0x200;
  1417.                                     if (sy > 450) sy -= 0x200;
  1418.  
  1419.                                     cps1_draw_tile16(bitmap,Machine->gfx[1],
  1420.                                         code+nxs+0x10*(ny-1-nys),
  1421.                                         col&0x1f,
  1422.                                         0,1,
  1423.                                         sx,sy,mask );
  1424.                                 }
  1425.                             }
  1426.                         }
  1427.                     }
  1428.                     else
  1429.                     {
  1430.                         if (colour &0x20)
  1431.                         {
  1432.                             for (nys=0; nys<ny; nys++)
  1433.                             {
  1434.                                 for (nxs=0; nxs<nx; nxs++)
  1435.                                 {
  1436.                                     sx = x+nxs*16;
  1437.                                     sy = y+nys*16;
  1438.                                     if (sx > 450) sx -= 0x200;
  1439.                                     if (sy > 450) sy -= 0x200;
  1440.  
  1441.                                     cps1_draw_tile16(bitmap,Machine->gfx[1],
  1442.                                         code+(nx-1)-nxs+0x10*nys,
  1443.                                         col&0x1f,
  1444.                                         1,0,
  1445.                                         sx,sy,mask
  1446.                                         );
  1447.                                 }
  1448.                             }
  1449.                         }
  1450.                         else
  1451.                         {
  1452.                             for (nys=0; nys<ny; nys++)
  1453.                             {
  1454.                                 for (nxs=0; nxs<nx; nxs++)
  1455.                                 {
  1456.                                     sx = x+nxs*16;
  1457.                                     sy = y+nys*16;
  1458.                                     if (sx > 450) sx -= 0x200;
  1459.                                     if (sy > 450) sy -= 0x200;
  1460.  
  1461.                                     cps1_draw_tile16(bitmap,Machine->gfx[1],
  1462.                                         code+nxs+0x10*nys,
  1463.                                         col&0x1f,
  1464.                                         0,0,
  1465.                                         sx,sy, mask);
  1466.                                 }
  1467.                             }
  1468.                         }
  1469.                     }
  1470.                 }
  1471.                 else
  1472.                 {
  1473.                     /* Simple case... 1 sprite */
  1474.                     cps1_draw_tile16(bitmap,Machine->gfx[1],
  1475.                            code,
  1476.                            col&0x1f,
  1477.                            colour&0x20,colour&0x40,
  1478.                            x,y,mask);
  1479.                 }
  1480.         }
  1481.     }
  1482. }
  1483.  
  1484.  
  1485.  
  1486. /***************************************************************************
  1487.  
  1488.   Scroll 2 (16x16 layer)
  1489.  
  1490.   Attribute word layout:
  1491.   0x0001    colour
  1492.   0x0002    colour
  1493.   0x0004    colour
  1494.   0x0008    colour
  1495.   0x0010    colour
  1496.   0x0020    X Flip
  1497.   0x0040    Y Flip
  1498.   0x0080    ??? Priority
  1499.   0x0100    ??? Priority
  1500.   0x0200
  1501.   0x0400
  1502.   0x0800
  1503.   0x1000
  1504.   0x2000
  1505.   0x4000
  1506.   0x8000
  1507.  
  1508.  
  1509. ***************************************************************************/
  1510.  
  1511. INLINE void cps1_palette_scroll2(unsigned short *base)
  1512. {
  1513.     int offs, code, colour;
  1514.     int basecode=cps1_game_config->bank_scroll2*0x04000;
  1515.  
  1516.     for (offs=cps1_scroll2_size-4; offs>=0; offs-=4)
  1517.     {
  1518.         code=basecode+READ_WORD(&cps1_scroll2[offs]);
  1519.         colour=READ_WORD(&cps1_scroll2[offs+2])&0x1f;
  1520.         if (code < cps1_max_tile16)
  1521.         {
  1522.             base[colour] |= cps1_tile16_pen_usage[code];
  1523.         }
  1524.     }
  1525. }
  1526.  
  1527. void cps1_render_scroll2_bitmap(struct osd_bitmap *bitmap)
  1528. {
  1529.     int sx, sy;
  1530.     int ny=(scroll2y>>4);      /* Rough Y */
  1531.     int base=cps1_game_config->bank_scroll2*0x04000;
  1532.     const int startcode=cps1_game_config->start_scroll2;
  1533.     const int endcode=cps1_game_config->end_scroll2;
  1534.     const int kludge=cps1_game_config->kludge;
  1535.  
  1536.     for (sx=CPS1_SCROLL2_WIDTH-1; sx>=0; sx--)
  1537.     {
  1538.         int n=ny;
  1539.         for (sy=0x09*2-1; sy>=0; sy--)
  1540.         {
  1541.             long newvalue;
  1542.             int offsy, offsx, offs, colour, code;
  1543.  
  1544.             n&=0x3f;
  1545.             offsy  = ((n&0x0f)*4 | ((n&0x30)*0x100))&0x3fff;
  1546.             offsx=(sx*0x040)&0xfff;
  1547.             offs=offsy+offsx;
  1548.  
  1549.             colour=READ_WORD(&cps1_scroll2[offs+2]);
  1550.  
  1551.             newvalue=*(long*)(&cps1_scroll2[offs]);
  1552.             if ( newvalue != *(long*)(&cps1_scroll2_old[offs]) )
  1553.             {
  1554.                 *(long*)(&cps1_scroll2_old[offs])=newvalue;
  1555.                 code=READ_WORD(&cps1_scroll2[offs]);
  1556.                 if ( code >= startcode && code <= endcode
  1557.                     /*
  1558.                     MERCS has an gap in the scroll 2 layout
  1559.                     (bad tiles at start of level 2)*/
  1560.                     &&    !(kludge == 4 && (code >= 0x1e00 && code < 0x5400))
  1561.                     )
  1562.                 {
  1563.                     code += base;
  1564.                     cps1_draw_tile16_bmp(bitmap,
  1565.                         Machine->gfx[2],
  1566.                         code,
  1567.                         colour&0x1f,
  1568.                         colour&0x20,colour&0x40,
  1569.                         16*sx, 16*n);
  1570.                 }
  1571.                 else
  1572.                 {
  1573.                     cps1_draw_blank16(bitmap, 16*sx, 16*n);
  1574.                 }
  1575.                 //cps1_print_debug_tile_info(bitmap, 16*sx, 16*n, colour,1);
  1576.             }
  1577.             n++;
  1578.         }
  1579.     }
  1580. }
  1581.  
  1582.  
  1583. void cps1_render_scroll2_high(struct osd_bitmap *bitmap)
  1584. {
  1585. #ifdef LAYER_DEBUG
  1586.     static int s=0;
  1587. #endif
  1588.     int sx, sy;
  1589.     int nxoffset=(scroll2x&0x0f)+32;    /* Smooth X */
  1590.     int nyoffset=(scroll2y&0x0f);    /* Smooth Y */
  1591.     int nx=(scroll2x>>4);      /* Rough X */
  1592.     int ny=(scroll2y>>4)-4;    /* Rough Y */
  1593.     int base=cps1_game_config->bank_scroll2*0x04000;
  1594.  
  1595.     for (sx=0; sx<0x32/2+4; sx++)
  1596.     {
  1597.         for (sy=0; sy<0x09*2; sy++)
  1598.         {
  1599.             int offsy, offsx, offs, colour, code, transp;
  1600.             int n;
  1601.             n=ny+sy+2;
  1602.             offsy  = ((n&0x0f)*4 | ((n&0x30)*0x100))&0x3fff;
  1603.             offsx=((nx+sx)*0x040)&0xfff;
  1604.             offs=offsy+offsx;
  1605.             offs &= 0x3fff;
  1606.  
  1607.             code=READ_WORD(&cps1_scroll2[offs]);
  1608.             colour=READ_WORD(&cps1_scroll2[offs+2]);
  1609.  
  1610.             transp=cps1_transparency_scroll[(colour & 0x0180)>>7];
  1611.  
  1612.             cps1_draw_tile16(bitmap,
  1613.                         Machine->gfx[2],
  1614.                         code+base,
  1615.                         colour&0x1f,
  1616.                         colour&0x20,colour&0x40,
  1617.                         16*sx-nxoffset,
  1618.                         16*sy-nyoffset,
  1619.                         transp);
  1620.         }
  1621.     }
  1622. }
  1623.  
  1624. void cps1_render_scroll2_low(struct osd_bitmap *bitmap)
  1625. {
  1626.       int scrly=-(scroll2y-0x20);
  1627.       int scrlx=-(scroll2x+0x40-0x20);
  1628.  
  1629.       if (cps1_flip_screen)
  1630.       {
  1631.             scrly=(CPS1_SCROLL2_HEIGHT*16)-scrly;
  1632.       }
  1633.  
  1634.       cps1_render_scroll2_bitmap(cps1_scroll2_bitmap);
  1635.  
  1636.       copyscrollbitmap(bitmap,cps1_scroll2_bitmap,1,&scrlx,1,&scrly,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1637. }
  1638.  
  1639.  
  1640. void cps1_render_scroll2_distort(struct osd_bitmap *bitmap)
  1641. {
  1642.     int scrly=-scroll2y;
  1643.     int i,scrollx[1024];
  1644.     int otheroffs;
  1645.  
  1646. /*
  1647.     Games known to use row scrolling:
  1648.  
  1649.     SF2
  1650.     Mega Twins (underwater, cave)
  1651.     Carrier Air Wing (hazy background at beginning of mission 8)
  1652.     Magic Sword (fire on floor 3; screen distort after continue)
  1653.     Varth (title screen)
  1654. */
  1655.  
  1656.     if (cps1_flip_screen)
  1657.         scrly=(CPS1_SCROLL2_HEIGHT*16)-scrly;
  1658.  
  1659.     cps1_render_scroll2_bitmap(cps1_scroll2_bitmap);
  1660.  
  1661.     otheroffs = cps1_port(CPS1_ROWSCROLL_OFFS);
  1662.  
  1663.     for (i = 0;i < 256;i++)
  1664.         scrollx[(i - scrly) & 0x3ff] = -(scroll2x+0x40-0x20) - READ_WORD(&cps1_other[(2*(i + otheroffs)) & 0x7ff]);
  1665.  
  1666.     scrly+=0x20;
  1667.  
  1668.     copyscrollbitmap(bitmap,cps1_scroll2_bitmap,1024,scrollx,1,&scrly,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1669. }
  1670.  
  1671.  
  1672. /***************************************************************************
  1673.  
  1674.   Scroll 3 (32x32 layer)
  1675.  
  1676.   Attribute word layout:
  1677.   0x0001    colour
  1678.   0x0002    colour
  1679.   0x0004    colour
  1680.   0x0008    colour
  1681.   0x0010    colour
  1682.   0x0020    X Flip
  1683.   0x0040    Y Flip
  1684.   0x0080
  1685.   0x0100
  1686.   0x0200
  1687.   0x0400
  1688.   0x0800
  1689.   0x1000
  1690.   0x2000
  1691.   0x4000
  1692.   0x8000
  1693.  
  1694. ***************************************************************************/
  1695.  
  1696. void cps1_palette_scroll3(unsigned short *base)
  1697. {
  1698.     int sx,sy;
  1699.     int nx=(scroll3x>>5)+1;
  1700.     int ny=(scroll3y>>5)-1;
  1701.     int basecode=cps1_game_config->bank_scroll3*0x01000;
  1702.  
  1703.     for (sx=0; sx<0x32/4+2; sx++)
  1704.     {
  1705.         for (sy=0; sy<0x20/4+2; sy++)
  1706.         {
  1707.             int offsy, offsx, offs, colour, code;
  1708.             int n;
  1709.             n=ny+sy;
  1710.             offsy  = ((n&0x07)*4 | ((n&0xf8)*0x0100))&0x3fff;
  1711.             offsx=((nx+sx)*0x020)&0x7ff;
  1712.             offs=offsy+offsx;
  1713.             offs &= 0x3fff;
  1714.             code=basecode+READ_WORD(&cps1_scroll3[offs]);
  1715.             if (cps1_game_config->kludge == 2 && code >= 0x01500)
  1716.             {
  1717.                    code -= 0x1000;
  1718.             }
  1719.             colour=READ_WORD(&cps1_scroll3[offs+2]);
  1720.             if (code < cps1_max_tile32)
  1721.             {
  1722.                 base[colour&0x1f] |= cps1_tile32_pen_usage[code];
  1723.             }
  1724.         }
  1725.     }
  1726. }
  1727.  
  1728.  
  1729. void cps1_render_scroll3(struct osd_bitmap *bitmap, int priority)
  1730. {
  1731.     int sx,sy;
  1732.     int nxoffset=scroll3x&0x1f;
  1733.     int nyoffset=scroll3y&0x1f;
  1734.     int nx=(scroll3x>>5)+1;
  1735.     int ny=(scroll3y>>5)-1;
  1736.     int basecode=cps1_game_config->bank_scroll3*0x01000;
  1737.     const int startcode=cps1_game_config->start_scroll3;
  1738.     const int endcode=cps1_game_config->end_scroll3;
  1739.  
  1740.     for (sx=1; sx<0x32/4+2; sx++)
  1741.     {
  1742.         for (sy=1; sy<0x20/4+2; sy++)
  1743.         {
  1744.             int offsy, offsx, offs, colour, code;
  1745.             int n;
  1746.             n=ny+sy;
  1747.             offsy  = ((n&0x07)*4 | ((n&0xf8)*0x0100))&0x3fff;
  1748.             offsx=((nx+sx)*0x020)&0x7ff;
  1749.             offs=offsy+offsx;
  1750.             offs &= 0x3fff;
  1751.             code=READ_WORD(&cps1_scroll3[offs]);
  1752.             if (code >= startcode && code <= endcode)
  1753.             {
  1754.                 int transp;
  1755.  
  1756.                 code+=basecode;
  1757.                 if (cps1_game_config->kludge == 2 && code >= 0x01500)
  1758.                 {
  1759.                        code -= 0x1000;
  1760.                 }
  1761.                 colour=READ_WORD(&cps1_scroll3[offs+2]);
  1762.                 if (priority)
  1763.                     transp=cps1_transparency_scroll[(colour & 0x0180)>>7];
  1764.                 else transp = 0x7fff;
  1765.  
  1766.                 cps1_draw_tile32(bitmap,Machine->gfx[3],
  1767.                         code,
  1768.                         colour&0x1f,
  1769.                         colour&0x20,colour&0x40,
  1770.                         32*sx-nxoffset,32*sy-nyoffset,
  1771.                         transp);
  1772.             }
  1773.         }
  1774.     }
  1775. }
  1776.  
  1777.  
  1778.  
  1779. void cps1_render_layer(struct osd_bitmap *bitmap, int layer, int distort)
  1780. {
  1781.     if (cps1_layer_enabled[layer])
  1782.     {
  1783.         switch (layer)
  1784.         {
  1785.             case 0:
  1786.                 cps1_render_sprites(bitmap);
  1787.                 break;
  1788.             case 1:
  1789.                 cps1_render_scroll1(bitmap, 0);
  1790.                 break;
  1791.             case 2:
  1792.                 if (distort)
  1793.                     cps1_render_scroll2_distort(bitmap);
  1794.                 else
  1795.                     cps1_render_scroll2_low(bitmap);
  1796.                 break;
  1797.             case 3:
  1798.                 cps1_render_scroll3(bitmap, 0);
  1799.                 break;
  1800.         }
  1801.     }
  1802. }
  1803.  
  1804. void cps1_render_high_layer(struct osd_bitmap *bitmap, int layer)
  1805. {
  1806.     if (cps1_layer_enabled[layer])
  1807.     {
  1808.         switch (layer)
  1809.         {
  1810.             case 0:
  1811.                 /* there are no high priority sprites */
  1812.                 break;
  1813.             case 1:
  1814.                 cps1_render_scroll1(bitmap, 1);
  1815.                 break;
  1816.             case 2:
  1817.                 cps1_render_scroll2_high(bitmap);
  1818.                 break;
  1819.             case 3:
  1820.                 cps1_render_scroll3(bitmap, 1);
  1821.                 break;
  1822.         }
  1823.     }
  1824. }
  1825.  
  1826.  
  1827. /***************************************************************************
  1828.  
  1829.     Refresh screen
  1830.  
  1831. ***************************************************************************/
  1832.  
  1833. void cps1_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  1834. {
  1835.     unsigned short palette_usage[cps1_palette_entries];
  1836.     int layercontrol,l0,l1,l2,l3;
  1837.     int i,offset;
  1838.     int distort_scroll2=0;
  1839.     int videocontrol=cps1_port(0x22);
  1840.     int old_flip;
  1841.  
  1842.  
  1843.     old_flip=cps1_flip_screen;
  1844.     cps1_flip_screen=videocontrol&0x8000;
  1845.     if (old_flip != cps1_flip_screen)
  1846.     {
  1847.          /* Mark all of scroll 2 as dirty */
  1848.         memset(cps1_scroll2_old, 0xff, cps1_scroll2_size);
  1849.     }
  1850.  
  1851.     layercontrol = READ_WORD(&cps1_output[cps1_game_config->layer_control]);
  1852.  
  1853.     distort_scroll2 = videocontrol & 0x01;
  1854.  
  1855.     /* Get video memory base registers */
  1856.     cps1_get_video_base();
  1857.  
  1858.     /* Find the offset of the last sprite in the sprite table */
  1859.     cps1_find_last_sprite();
  1860.  
  1861.     /* Build palette */
  1862.     cps1_build_palette();
  1863.  
  1864.     /* Compute the used portion of the palette */
  1865.     memset (palette_usage, 0, sizeof (palette_usage));
  1866.     cps1_palette_sprites (&palette_usage[cps1_obj_palette]);
  1867.     if (cps1_layer_enabled[1])
  1868.         cps1_palette_scroll1 (&palette_usage[cps1_scroll1_palette]);
  1869.     if (cps1_layer_enabled[2])
  1870.         cps1_palette_scroll2 (&palette_usage[cps1_scroll2_palette]);
  1871.     else
  1872.         memset(cps1_scroll2_old, 0xff, cps1_scroll2_size);
  1873.     if (cps1_layer_enabled[3])
  1874.         cps1_palette_scroll3 (&palette_usage[cps1_scroll3_palette]);
  1875.  
  1876.     for (i = offset = 0; i < cps1_palette_entries; i++)
  1877.     {
  1878.         int usage = palette_usage[i];
  1879.         if (usage)
  1880.         {
  1881.             int j;
  1882.             for (j = 0; j < 15; j++)
  1883.             {
  1884.                 if (usage & (1 << j))
  1885.                     palette_used_colors[offset++] = PALETTE_COLOR_USED;
  1886.                 else
  1887.                     palette_used_colors[offset++] = PALETTE_COLOR_UNUSED;
  1888.             }
  1889.             palette_used_colors[offset++] = PALETTE_COLOR_TRANSPARENT;
  1890.         }
  1891.         else
  1892.         {
  1893.             memset (&palette_used_colors[offset], PALETTE_COLOR_UNUSED, 16);
  1894.             offset += 16;
  1895.         }
  1896.     }
  1897.  
  1898.     if (palette_recalc ())
  1899.     {
  1900.          /* Mark all of scroll 2 as dirty */
  1901.         memset(cps1_scroll2_old, 0xff, cps1_scroll2_size);
  1902.     }
  1903.  
  1904.     /* Blank screen */
  1905. //    fillbitmap(bitmap,palette_transparent_pen,&Machine->drv->visible_area);
  1906. // TODO: the draw functions don't clip correctly at the sides of the screen, so
  1907. // for now let's clear the whole bitmap otherwise ctrl-f11 would show wrong counts
  1908.     fillbitmap(bitmap,palette_transparent_pen,0);
  1909.  
  1910.  
  1911.     /* Draw layers */
  1912.     l0 = (layercontrol >> 0x06) & 03;
  1913.     l1 = (layercontrol >> 0x08) & 03;
  1914.     l2 = (layercontrol >> 0x0a) & 03;
  1915.     l3 = (layercontrol >> 0x0c) & 03;
  1916.  
  1917.     cps1_render_layer(bitmap,l0,distort_scroll2);
  1918.     cps1_render_layer(bitmap,l1,distort_scroll2);
  1919.     if (l1 == 0) cps1_render_high_layer(bitmap,l0);    /* overlay sprites */
  1920.     cps1_render_layer(bitmap,l2,distort_scroll2);
  1921.     if (l2 == 0) cps1_render_high_layer(bitmap,l1);    /* overlay sprites */
  1922.     cps1_render_layer(bitmap,l3,distort_scroll2);
  1923.     if (l3 == 0) cps1_render_high_layer(bitmap,l2);    /* overlay sprites */
  1924.  
  1925. #if CPS1_DUMP_VIDEO
  1926.     if (keyboard_pressed(KEYCODE_F))
  1927.     {
  1928.         cps1_dump_video();
  1929.     }
  1930. #endif
  1931. }
  1932.  
  1933. void cps1_eof_callback(void)
  1934. {
  1935.     /* Get video memory base registers */
  1936.     cps1_get_video_base();
  1937.  
  1938.     /* Mish: 181099: Buffer sprites for next frame - the hardware must do
  1939.         this at the end of vblank */
  1940.     memcpy(cps1_buffered_obj,cps1_obj,cps1_obj_size);
  1941. }
  1942.  
  1943.  
  1944. #include "cps2.c"
  1945.